/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuexiang.xui_lib.component;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.ScrollView;
import ohos.agp.render.Canvas;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

/**
 * 网格布局
 *
 * @author jiangjianming
 * @since 2021-04-13
 */
public class GridLayout extends ScrollView implements Component.DrawTask {

    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");
    private static final int DEFAULT_COUNT = 3;

    private int spacing;
    private int spanCount = DEFAULT_COUNT;

    private GridProvider mGridProvider;
    private DirectionalLayout mScrollContainer;
    private OnItemClickListener listener;

    /**
     * 点击事件
     *
     * @since 2021-04-13
     */
    public interface OnItemClickListener {
        /**
         * item点击
         *
         * @param component 点击的component
         * @param position 位置下标
         */
        void onItemClick(Component component, int position);
    }

    /**
     * 网格布局
     *
     * @param context 上下文
     */
    public GridLayout(Context context) {
        this(context, null);
    }

    /**
     * 网格布局
     *
     * @param context 上下文
     * @param attrSet 参数
     */
    public GridLayout(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    /**
     * 网格布局
     *
     * @param context 上下文
     * @param attrSet 参数
     * @param styleName 样式
     */
    public GridLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setLayoutConfig(createRootViewConfig());
        mScrollContainer = createContainerView(context);
        initAttrSet(context, attrSet);
        addComponent(mScrollContainer);
        addDrawTask(this);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        fillViews();
    }

    private void initAttrSet(Context context, AttrSet attrSet) {
        spacing = AttrHelper.vp2px(7.5f, context);
    }

    /**
     * 设置列数
     *
     * @param count 列数
     */
    public void setSpanCount(int count) {
        if (count < 0) {
            count = 0;
        }
        this.spanCount = count;
    }

    public void setSpacing(int spacing) {
        this.spacing = spacing;
    }

    public void setProvider(GridProvider provider) {
        this.mGridProvider = provider;
    }

    /**
     * 刷新
     */
    public void notifyDataSetChange() {
        fillViews();
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.listener = onItemClickListener;
    }

    private void fillViews() {
        if (mGridProvider == null || mGridProvider.getCount() < 0) {
            return;
        }
        boolean isFillEnd = false;
        int count = mGridProvider.getCount();
        mScrollContainer.removeAllComponents();
        int countIndex = 0;
        for (int i = 0; i < count; i++) {
            DirectionalLayout container = createColumnContainer();
            for (int j = 0; j < spanCount; j++) {
                // 添加列
                Component child = mGridProvider.getComponent(countIndex);
                child.setTag(countIndex);
                if (listener != null) {
                    child.setClickedListener(component ->
                        listener.onItemClick(component, (Integer) component.getTag()));
                }
                createColumn(container, child);
                fillSpacing(j, child);
                if (countIndex == count - 1) {
                    isFillEnd = true;
                    onFillEmpty(container);
                    break;
                }
                countIndex++;
            }
            if (i > 0) {
                container.setMarginTop(spacing);
            }
            mScrollContainer.addComponent(container);
            if (isFillEnd) {
                break;
            }
        }
    }

    private void fillSpacing(int countIndex, Component child) {
        if (spacing == 0) {
            return;
        }
        int sp = spacing / 2;
        if (countIndex == 0) {
            // 第一个
            child.setMarginRight(sp);
        } else if (countIndex == spanCount - 1) {
            // 最后一个
            child.setMarginLeft(sp);
        } else {
            // 中间页面
            child.setMarginLeft(sp);
            child.setMarginRight(sp);
        }
    }

    private void onFillEmpty(DirectionalLayout container) {
        int fillCount = fillCount();
        for (int i = 0; i < fillCount; i++) {
            Component component = fillEmpty(container);
            fillSpacing(spanCount - (i + 1), component);
        }
    }

    private void createColumn(DirectionalLayout container, Component child) {
        ComponentContainer.LayoutConfig layoutConfig = child.getLayoutConfig();
        DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig(0, layoutConfig.height);
        config.weight = 1;
        container.addComponent(child, config);
    }

    private Component fillEmpty(DirectionalLayout container) {
        DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig(0, 1);
        config.weight = 1;
        Component component = new Component(getContext());
        container.addComponent(component, config);
        return component;
    }

    /**
     * 计算还需填充空白的个数
     *
     * @return int
     */
    private int fillCount() {
        int count = mGridProvider.getCount();
        if (count <= spanCount) {
            return spanCount - count;
        }
        if (count % spanCount == 0) {
            return 0;
        } else {
            // 余的则是需要补充的
            return spanCount - (count % spanCount);
        }
    }

    /**
     * 创建列的容器
     *
     * @return DirectionalLayout
     */
    private DirectionalLayout createColumnContainer() {
        DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig(
            ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
        DirectionalLayout columnContainer = new DirectionalLayout(getContext());
        columnContainer.setLayoutConfig(config);
        columnContainer.setOrientation(DirectionalLayout.HORIZONTAL);
        return columnContainer;
    }

    /**
     * 创建ScrollView 的根容器
     *
     * @param context
     * @return DirectionalLayout
     */
    private DirectionalLayout createContainerView(Context context) {
        DirectionalLayout rootView = new DirectionalLayout(context);
        DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig(
            ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
        rootView.setLayoutConfig(config);
        rootView.setOrientation(DirectionalLayout.VERTICAL);
        return rootView;
    }

    private ComponentContainer.LayoutConfig createRootViewConfig() {
        LayoutConfig config = new LayoutConfig(
            ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
        return config;
    }
}
